package com.example.design.mveldemo;

import org.mvel2.MVEL;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.integration.impl.MapVariableResolverFactory;

import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MvelTest {

    public static void main(String[] args) {
        // 属性表达式
        property();

        // 布尔表达式
        bool();

        // 复合表达式
        complex();

        // 返回值
        retrun();

        // 一元操作符
        // new：用来实例化对象
        newObject();
        // with语法：with可以为对象的多个属性赋值
        with();
//        assert：用一个AssertionError 断言一个值的对错，例：assert foo != null
//        isdef：用来判断一个变量在某个范围内是否定义，例：isdef variableName
//         ！: 布尔取反操作符，例： ！true == false

        // 逻辑运算符
//        &&	与
//        ||	或
//        or	用于多个值进行逻辑或运算
        logic();

//        数字运算符
//        包括加减乘除（+，-，*，/）等等

//        其他运算符
//        +，字符串连接运算，如：“foo” +“bar”
//        #，字符连接运算，如：1 # 2返回"12"
//        in，投影整个项目集合，如：(foo in list)
//        =，赋值运算符，如：var = “foobar”

//        MVEL对列表、数组、map的操作
//        https://blog.csdn.net/ylldzz/article/details/133981733
        list();
        array();
        map();

//        Null-Safe Bean Navigation
//        有时，当你的表达式中会含有null元素时，这时就需要你进行一个为空判断，否则就会发生错误。当你使用null-safe操作符时你可以简化这个操作：user.?manager.name

//        集合
//        集合的遍历也可以通过简单的语法来实现：
//        List：可以像访问数组一样访问List，如：user[5],这等价与java代码中的user.get(5);
//        Map:Map的访问和访问数组也非常相似，不同的是，在访问Map时索引值可以是任意对象，如：user[“foobar”]这等价于java代码中的user.get(“foobar”);
//        当Map的key是String类型时，还可以使用特殊的方式来访问，如：user.foobar,也就是允许你把map本身看成一个虚拟的对象，来访问其属性


    }

    private static void map() {
        String expression = "['Bob' : new com.example.design.mveldemo.User('Bob',1), 'Michael' : new com.example.design.mveldemo.User('Michael',2)]";
        Map o = (Map ) MVEL.eval(expression);
        User u = (User) o.get("Bob");
        System. out.println(u.getName());
    }

    private static void array() {
        String expression = "{'Jim','Bob','Tom'}";
        Object str = MVEL.eval(expression);
        if(str.getClass().isArray()){
            System. out.println(Array.get(str, 0));
        }
    }

    private static void list() {
        String expression = "['Jim','Bob','Tom']";
        List< String> l = (List<String>) MVEL. eval(expression);
        for(String str:l){
            System. out.println(str);
        }
    }

    private static void logic() {
        Map<String, Integer> m = new HashMap<>();
        m.put("a", 100);
        m.put("b", 50);
        Object obj = MVEL.eval("a>10 && b >10", m);
        System.out.println(obj);
    }

    private static void retrun() {
        // 创建一个上下文并设置变量
        Map<String, Object> context = new HashMap<>();
        // MVEL表达式
        String expression = "a=10;b=(a=2)+10;a";
        // 使用VariableResolverFactory将上下文传递给MVEL
        VariableResolverFactory functionFactory = new MapVariableResolverFactory(context);
        // 执行MVEL表达式并获取结果
        Object result = MVEL.eval(expression, functionFactory);
        // 输出结果
        System.out.println("Result: " + result);
    }


    private static void newObject() {
        User obj = (User) MVEL.eval("new com.example.design.mveldemo.User('hello',11)");
        System.out.println(obj);
    }

    /**
     * 在MVEL中，一段语句中可以写任意多个语句，每个语句以；隔开，最后一个语句没有分号。如以下这个语句：
     */
    private static void complex() {
        String com = "a = a+10;a=+11";
        Map<String, Object> m = new HashMap<>();
        m.put("a", 0);
        Object obj = MVEL.eval(com, m);
        System.out.println(obj);
    }

    /**
     * MVEL的布尔表达式和JAVA一样有优先级，包括通过括号来控制执行顺序。
     * ==	等于
     * >	大于
     * <	小于
     * !=	不等于
     * contains	包含。如果左边的字符串包含右边的字符串内容，返回true
     * is/instanceof	实例类型检查，如果实例类型是右边的类型，返回true
     * istrsim	字符相似
     * sounds	读音相似
     * ~=	正则表达式测试
     */
    private static void bool() {
        Map<String, Integer> m = new HashMap<>();
        m.put("a", 100);
        Object obj = MVEL.eval("a>10", m);
        System.out.println(obj);

        // 读音相似
        String composite = "'foobar' soundslike 'fubar'";
        Object objk = MVEL.eval(composite);
        System.out.println(objk);

    }

    private static void with() {
        User user = new User();
        Map<String, Object> m = new HashMap<>();
        m.put("user", user);
        MVEL.eval("with(user){name='张三',age=30}", m);
        System.out.println(user);
    }

    private static void property() {
        User user = new User("zhangsan", 123);
        Map<String, Object> m = new HashMap<>();
        m.put("user", user);

        // 获取属性
        Object o = MVEL.eval("user.name", m);
        System.out.println(o);

        // 设置属性
        MVEL.eval("user.age=22", m);
        System.out.println(user.getAge());
    }
}
